home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / comm / tcp / wu_ftpd_37_21.lha / wu-ftpd / src / extensions.c < prev    next >
C/C++ Source or Header  |  1994-09-12  |  28KB  |  991 lines

  1. /* Copyright (c) 1993, 1994  Washington University in Saint Louis
  2.  * All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions are
  6.  * met: 1. Redistributions of source code must retain the above copyright
  7.  * notice, this list of conditions and the following disclaimer. 2.
  8.  * Redistributions in binary form must reproduce the above copyright notice,
  9.  * this list of conditions and the following disclaimer in the documentation
  10.  * and/or other materials provided with the distribution. 3. All advertising
  11.  * materials mentioning features or use of this software must display the
  12.  * following acknowledgement: This product includes software developed by the
  13.  * Washington University in Saint Louis and its contributors. 4. Neither the
  14.  * name of the University nor the names of its contributors may be used to
  15.  * endorse or promote products derived from this software without specific
  16.  * prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY WASHINGTON UNIVERSITY AND CONTRIBUTORS
  19.  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21.  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASHINGTON
  22.  * UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24.  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  28.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29.  * POSSIBILITY OF SUCH DAMAGE.
  30.  */
  31.  
  32. #include "config.h"
  33.  
  34. #include <stdio.h>
  35. #include <errno.h>
  36. #include <string.h>
  37. #ifdef SYSSYSLOG
  38. #include <sys/syslog.h>
  39. #else
  40. #include <syslog.h>
  41. #endif
  42. #include <time.h>
  43. #include <pwd.h>
  44. #include <grp.h>
  45.  
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #include <sys/file.h>
  49. #ifdef AMIGA
  50. #include <libraries/multiuser.h>
  51. #include <proto/multiuser.h>
  52. #endif
  53. #include <sys/param.h>
  54.  
  55. #ifdef HAVE_STATVFS
  56. #include <sys/statvfs.h>
  57. #endif
  58.  
  59. #include <arpa/ftp.h>
  60.  
  61. #include "pathnames.h"
  62. #include "extensions.h"
  63. #ifdef AMIGA
  64. #include "ftw.h"
  65. #else
  66. #include "support/ftw.h"
  67. #endif
  68.  
  69. #ifdef HAVE_REGEX_H
  70. #include <regex.h>
  71. #endif
  72.  
  73. #ifdef AMIGA
  74. #include <regexp.h>
  75. #endif
  76.  
  77. #if defined(REGEX) && defined(SOLARIS_21)
  78. #include <libgen.h>
  79. #endif
  80.  
  81. extern int fnmatch(),
  82.   type,
  83.   transflag,
  84.   autospout_free,
  85.   data,
  86.   anonymous,
  87.   guest;
  88. extern char **ftpglob(register char *v),
  89.  *globerr,
  90.   remotehost[],
  91.   hostname[],
  92.  *autospout,
  93.   Shutdown[];
  94.  
  95. char shuttime[30],
  96.   denytime[30],
  97.   disctime[30];
  98.  
  99. #ifndef REGEX
  100. char *re_comp();
  101. #elif defined(M_UNIX)
  102. extern char *regcmp(), *regex();
  103. #endif
  104.  
  105. extern FILE *dataconn(char *name, off_t size, char *mode);
  106. FILE *dout;
  107.  
  108. time_t newer_time;
  109.  
  110. int show_fullinfo;
  111.  
  112. check_newer(char *path, struct stat *st, int flag)
  113. {
  114.  
  115.     if (st->st_mtime > newer_time) {
  116.         if (show_fullinfo != 0) {
  117.             if (flag == FTW_F || flag == FTW_D) {
  118.                 fprintf(dout, "%s %d %d %s", flag == FTW_F ? "F" : "D",
  119.                         st->st_size, st->st_mtime, path);
  120.             }
  121.         } else if (flag == FTW_F)
  122.             fprintf(dout, "%s", path);
  123.     }
  124.     return 0;
  125. }
  126.  
  127. #ifdef HAVE_STATVFS
  128. int getSize(s)
  129. char *s;
  130. {
  131.     int c;
  132.     struct statvfs buf;
  133.  
  134.     if (( c = statvfs(s, &buf)) != 0)
  135.         return(0);
  136.  
  137.     return(buf.f_bavail * buf.f_frsize / 1024);
  138. }
  139. #endif
  140.  
  141. /*************************************************************************/
  142. /* FUNCTION  : msg_massage                                               */
  143. /* PURPOSE   : Scan a message line for magic cookies, replacing them as  */
  144. /*             needed.                                                   */
  145. /* ARGUMENTS : pointer input and output buffers                          */
  146. /*************************************************************************/
  147.  
  148. int
  149. msg_massage(char *inbuf, char *outbuf)
  150. {
  151.     char *inptr = inbuf;
  152.     char *outptr = outbuf;
  153.     char buffer[MAXPATHLEN];
  154.     time_t curtime;
  155.     int limit;
  156.     extern struct passwd *pw;
  157.     struct aclmember *entry = NULL;
  158.  
  159.     (void) time(&curtime);
  160.     (void) acl_getclass(buffer);
  161.  
  162.     limit = acl_getlimit(buffer, NULL);
  163.  
  164.     while (*inptr) {
  165.         if (*inptr != '%')
  166.             *outptr++ = *inptr;
  167.         else {
  168.             switch (*++inptr) {
  169.             case 'E':
  170.                 if ( (getaclentry("email", &entry)) && ARG0 )
  171.                     sprintf(outptr, "%s", ARG0); 
  172.                 break;
  173.             case 'N': 
  174.                 sprintf(outptr, "%d", acl_countusers(buffer)); 
  175.                 break; 
  176.             case 'M':
  177.                 sprintf(outptr, "%d", limit);
  178.                 break;
  179.  
  180.             case 'T':
  181.                 strncpy(outptr, ctime(&curtime), 24);
  182.                 *(outptr + 24) = NULL;
  183.                 break;
  184.  
  185.             case 'F':
  186. #ifdef HAVE_STATVFS
  187.                 sprintf(outptr, "%lu", getSize("."));
  188. #endif
  189.                 break;
  190.  
  191.             case 'C':
  192. #ifdef HAVE_GETCWD
  193.                 (void) getcwd(outptr, MAXPATHLEN);
  194. #else
  195.                 (void) getwd(outptr);
  196. #endif
  197.                 break;
  198.  
  199.             case 'R':
  200.                 strcpy(outptr, remotehost);
  201.                 break;
  202.  
  203.             case 'L':
  204.                 strcpy(outptr, hostname);
  205.                 break;
  206.  
  207.             case 'U':
  208.                 strcpy(outptr, pw->pw_name);
  209.                 break;
  210.  
  211.             case 's':
  212.                 strncpy(outptr, shuttime, 24);
  213.                 *(outptr + 24) = NULL;
  214.                 break;
  215.  
  216.             case 'd':
  217.                 strncpy(outptr, disctime, 24);
  218.                 *(outptr + 24) = NULL;
  219.                 break;
  220.  
  221.             case 'r':
  222.                 strncpy(outptr, denytime, 24);
  223.                 *(outptr + 24) = NULL;
  224.                 break;
  225.  
  226.             case '%':
  227.                 *outptr++ = '%';
  228.                 *outptr = '\0';
  229.                 break;
  230.  
  231.             default:
  232.                 *outptr++ = '%';
  233.                 *outptr++ = '?';
  234.                 *outptr = '\0';
  235.                 break;
  236.             }
  237.             while (*outptr)
  238.                 outptr++;
  239.         }
  240.         inptr++;
  241.     }
  242.     *outptr = NULL;
  243. }
  244.  
  245. /*************************************************************************/
  246. /* FUNCTION  : cwd_beenhere                                              */
  247. /* PURPOSE   : Return 1 if the user has already visited this directory   */
  248. /*             via C_WD.                                                 */
  249. /* ARGUMENTS : a power-of-two directory function code (README, MESSAGE)  */
  250. /*************************************************************************/
  251.  
  252. int
  253. cwd_beenhere(int dircode)
  254. {
  255.     struct dirlist {
  256.         struct dirlist *next;
  257.         int dircode;
  258.         char dirname[1];
  259.     };
  260.  
  261.     static struct dirlist *head = NULL;
  262.     struct dirlist *curptr;
  263.     char cwd[MAXPATHLEN];
  264.  
  265. #ifdef AMIGA
  266.     (void) realpath("", cwd);
  267. #else
  268.     (void) realpath(".", cwd);
  269. #endif
  270.  
  271.     for (curptr = head; curptr != NULL; curptr = curptr->next)
  272.         if (strcmp(curptr->dirname, cwd) == NULL) {
  273.             if (!(curptr->dircode & dircode)) {
  274.                 curptr->dircode |= dircode;
  275.                 return (0);
  276.             }
  277.             return (1);
  278.         }
  279.     curptr = (struct dirlist *) malloc(strlen(cwd) + 1 + sizeof(struct dirlist));
  280.  
  281.     if (curptr != NULL) {
  282.         curptr->next = head;
  283.         head = curptr;
  284.         curptr->dircode = dircode;
  285.         strcpy(curptr->dirname, cwd);
  286.     }
  287.     return (0);
  288. }
  289.  
  290. /*************************************************************************/
  291. /* FUNCTION  : show_banner                                               */
  292. /* PURPOSE   : Display a banner on the user's terminal before login      */
  293. /* ARGUMENTS : reply code to use                                         */
  294. /*************************************************************************/
  295.  
  296. void
  297. show_banner(int msgcode)
  298. {
  299.     char *crptr,
  300.       linebuf[1024],
  301.       outbuf[1024];
  302.     struct aclmember *entry = NULL;
  303.     FILE *infile;
  304.  
  305.     /* banner <path> */
  306.     while (getaclentry("banner", &entry)) {
  307.         if (ARG0 && strlen(ARG0) > 0) {
  308.             infile = fopen(ARG0, "r");
  309.             if (infile) {
  310.                 while (fgets(linebuf, 255, infile) != NULL) {
  311.                     if ((crptr = strchr(linebuf, '\n')) != NULL)
  312.                         *crptr = '\0';
  313.                     msg_massage(linebuf, outbuf);
  314.                     lreply(msgcode, "%s", outbuf);
  315.                 }
  316.                 fclose(infile);
  317.                 lreply(msgcode, "");
  318.             }
  319.         }
  320.     }
  321. }
  322.  
  323. /*************************************************************************/
  324. /* FUNCTION  : show_message                                              */
  325. /* PURPOSE   : Display a message on the user's terminal if the current   */
  326. /*             conditions are right                                      */
  327. /* ARGUMENTS : reply code to use, LOG_IN|CMD                             */
  328. /*************************************************************************/
  329.  
  330. void
  331. show_message(int msgcode, int mode)
  332. {
  333.     char *crptr,
  334.       linebuf[1024],
  335.       outbuf[1024],
  336.       class[MAXPATHLEN],
  337.       cwd[MAXPATHLEN];
  338.     int show,
  339.       which;
  340.     struct aclmember *entry = NULL;
  341.     FILE *infile;
  342.  
  343.     if (cwd_beenhere(1) != 0)
  344.         return;
  345.  
  346. #ifdef HAVE_GETCWD
  347.     (void) getcwd(cwd,MAXPATHLEN-1);
  348. #else
  349.     (void) getwd(cwd);
  350. #endif
  351.     (void) acl_getclass(class);
  352.  
  353.     /* message <path> [<when> [<class>]] */
  354.     while (getaclentry("message", &entry)) {
  355.         if (!ARG0)
  356.             continue;
  357.         show = 0;
  358.  
  359.         if (mode == LOG_IN && (!ARG1 || !strcasecmp(ARG1, "login")))
  360.             if (!ARG2)
  361.                 show++;
  362.             else {
  363.                 for (which = 2; (which < MAXARGS) && ARG[which]; which++)
  364.                     if (strcasecmp(class, ARG[which]) == NULL)
  365.                         show++;
  366.             }
  367.         if (mode == C_WD && ARG1 && !strncasecmp(ARG1, "cwd=", 4) &&
  368.             (!strcmp((ARG1) + 4, cwd) || *(ARG1 + 4) == '*' ||
  369.             fnmatch((ARG1) + 4, cwd, FNM_PATHNAME)))
  370.             if (!ARG2)
  371.                 show++;
  372.             else {
  373.                 for (which = 2; (which < MAXARGS) && ARG[which]; which++)
  374.                     if (strcasecmp(class, ARG[which]) == NULL)
  375.                         show++;
  376.             }
  377.         if (show && strlen(ARG0) > 0) {
  378.             infile = fopen(ARG0, "r");
  379.             if (infile) {
  380.                 while (fgets(linebuf, 255, infile) != NULL) {
  381.                     if ((crptr = strchr(linebuf, '\n')) != NULL)
  382.                         *crptr = '\0';
  383.                     msg_massage(linebuf, outbuf);
  384.                     lreply(msgcode, "%s", outbuf);
  385.                 }
  386.                 fclose(infile);
  387.                 lreply(msgcode, "");
  388.             }
  389.         }
  390.     }
  391. }
  392.  
  393. /*************************************************************************/
  394. /* FUNCTION  : show_readme                                               */
  395. /* PURPOSE   : Display a message about a README file to the user if the  */
  396. /*             current conditions are right                              */
  397. /* ARGUMENTS : pointer to ACL buffer, reply code, LOG_IN|C_WD            */
  398. /*************************************************************************/
  399.  
  400. void
  401. show_readme(int code, int mode)
  402. {
  403.     char **filelist,
  404.       class[MAXPATHLEN],
  405.       cwd[MAXPATHLEN];
  406.     int show,
  407.       which,
  408.       days;
  409.     time_t clock;
  410.  
  411.     struct stat buf;
  412.     struct tm *tp;
  413.     struct aclmember *entry = NULL;
  414.  
  415.     if (cwd_beenhere(2) != 0)
  416.         return;
  417.  
  418. #ifdef HAVE_GETCWD
  419.     (void) getcwd(cwd,MAXPATHLEN-1);
  420. #else
  421.     (void) getwd(cwd);
  422. #endif
  423.     (void) acl_getclass(class);
  424.  
  425.     /* readme  <path> {<when>} */
  426.     while (getaclentry("readme", &entry)) {
  427.         if (!ARG0)
  428.             continue;
  429.         show = 0;
  430.  
  431.         if (mode == LOG_IN && (!ARG1 || !strcasecmp(ARG1, "login")))
  432.             if (!ARG2)
  433.                 show++;
  434.             else {
  435.                 for (which = 2; (which < MAXARGS) && ARG[which]; which++)
  436.                     if (strcasecmp(class, ARG[which]) == NULL)
  437.                         show++;
  438.             }
  439.         if (mode == C_WD && ARG1 && !strncasecmp(ARG1, "cwd=", 4)
  440.             && (!strcmp((ARG1) + 4, cwd) || *(ARG1 + 4) == '*' ||
  441.                 fnmatch((ARG1) + 4, cwd, FNM_PATHNAME)))
  442.             if (!ARG2)
  443.                 show++;
  444.             else {
  445.                 for (which = 2; (which < MAXARGS) && ARG[which]; which++)
  446.                     if (strcasecmp(class, ARG[which]) == NULL)
  447.                         show++;
  448.             }
  449.         if (show) {
  450.             globerr = NULL;
  451.             filelist = ftpglob(ARG0);
  452.             if (!globerr) {
  453.                 while (filelist && *filelist) {
  454.                    errno = 0;
  455.                    if (!stat(*filelist, &buf)) {
  456.                        lreply(code, "Please read the file %s", *filelist);
  457.                        (void) time(&clock);
  458.                        tp = localtime(&clock);
  459.                        days = 365 * tp->tm_year + tp->tm_yday;
  460.                        tp = localtime(&buf.st_mtime);
  461.                        days -= 365 * tp->tm_year + tp->tm_yday;
  462. /*
  463.                        if (days == 0) {
  464.                          lreply(code, "  it was last modified on %.24s - Today",
  465.                            ctime(&buf.st_mtime));
  466.                        } else {
  467. */
  468.                          lreply(code, 
  469.                            "  it was last modified on %.24s - %d day%s ago",
  470.                            ctime(&buf.st_mtime), days, days == 1 ? "" : "s");
  471. /*
  472.                        }
  473. */
  474.                    }
  475.                    filelist++;
  476.                 }
  477.             }
  478.         }
  479.     }
  480. }
  481.  
  482. /*************************************************************************/
  483. /* FUNCTION  : deny_badxfertype                                          */
  484. /* PURPOSE   : If user is in ASCII transfer mode and tries to retrieve a */
  485. /*             binary file, abort transfer and display appropriate error */
  486. /* ARGUMENTS : message code to use for denial, path of file to check for */
  487. /*             binary contents or NULL to assume binary file             */
  488. /*************************************************************************/
  489.  
  490. int
  491. deny_badasciixfer(int msgcode, char *filepath)
  492. {
  493.  
  494.     if (type == TYPE_A && !*filepath) {
  495.         reply(msgcode, "This is a BINARY file, using ASCII mode to transfer will corrupt it.");
  496.         return (1);
  497.     }
  498.     /* The hooks are here to prevent transfers of actual binary files, not
  499.      * just TAR or COMPRESS mode files... */
  500.     return (0);
  501. }
  502.  
  503. /*************************************************************************/
  504. /* FUNCTION  : is_shutdown                                               */
  505. /* PURPOSE   :                                                           */
  506. /* ARGUMENTS :                                                           */
  507. /*************************************************************************/
  508.  
  509. int
  510. is_shutdown(int quiet)
  511. {
  512.     static struct tm tmbuf;
  513.     static struct stat s_last;
  514.     static time_t last = 0,
  515.       shut,
  516.       deny,
  517.       disc;
  518.  
  519.     static char text[2048];
  520.  
  521.     struct stat s_cur;
  522.  
  523.     FILE *fp;
  524.  
  525.     int deny_off,
  526.       disc_off;
  527.  
  528.     time_t curtime = time(NULL);
  529.  
  530.     char buf[1024],
  531.       linebuf[1024];
  532.  
  533.     if (Shutdown[0] == '\0' || stat(Shutdown, &s_cur))
  534.         return (0);
  535.  
  536.     if (s_last.st_mtime != s_cur.st_mtime) {
  537.         s_last = s_cur;
  538.  
  539.         fp = fopen(Shutdown, "r");
  540.         if (fp == NULL)
  541.             return (0);
  542.         fgets(buf, sizeof(buf), fp);
  543.         if (sscanf(buf, "%d %d %d %d %d %d %d", &tmbuf.tm_year, &tmbuf.tm_mon,
  544.         &tmbuf.tm_mday, &tmbuf.tm_hour, &tmbuf.tm_min, &deny, &disc) != 7) {
  545.             return (0);
  546.         }
  547.         deny_off = 3600 * (deny / 100) + 60 * (deny % 100);
  548.         disc_off = 3600 * (disc / 100) + 60 * (disc % 100);
  549.  
  550.         tmbuf.tm_year -= 1900;
  551.         tmbuf.tm_isdst = -1;
  552.         shut = mktime(&tmbuf);
  553.         strcpy(shuttime, ctime(&shut));
  554.  
  555.         disc = shut - disc_off;
  556.         strcpy(disctime, ctime(&disc));
  557.  
  558.         deny = shut - deny_off;
  559.         strcpy(denytime, ctime(&deny));
  560.  
  561.         text[0] = '\0';
  562.  
  563.         while (fgets(buf, sizeof(buf), fp) != NULL) {
  564.             msg_massage(buf, linebuf);
  565.             if ((strlen(text) + strlen(linebuf)) < sizeof(text))
  566.                 strcat(text, linebuf);
  567.         }
  568.  
  569.         (void) fclose(fp);
  570.     }
  571.     /* if last == 0, then is_shutdown() only called with quiet == 1 so far */
  572.     if (last == 0 && !quiet) {
  573.         autospout = text;       /* warn them for the first time */
  574.         autospout_free = 0;
  575.         last = curtime;
  576.     }
  577.     /* if past disconnect time, tell caller to drop 'em */
  578.     if (curtime > disc)
  579.         return (1);
  580.  
  581.     /* if less than 60 seconds to disconnection, warn 'em continuously */
  582.     if (curtime > (disc - 60) && !quiet) {
  583.         autospout = text;
  584.         autospout_free = 0;
  585.         last = curtime;
  586.     }
  587.     /* if less than 15 minutes to disconnection, warn 'em every 5 mins */
  588.     if (curtime > (disc - 60 * 15)) {
  589.         if ((curtime - last) > (60 * 5) && !quiet) {
  590.             autospout = text;
  591.             autospout_free = 0;
  592.             last = curtime;
  593.         }
  594.     }
  595.     /* if less than 24 hours to disconnection, warn 'em every 30 mins */
  596.     if (curtime < (disc - 24 * 60 * 60) && !quiet) {
  597.         if ((curtime - last) > (60 * 30)) {
  598.             autospout = text;
  599.             autospout_free = 0;
  600.             last = curtime;
  601.         }
  602.     }
  603.     /* if more than 24 hours to disconnection, warn 'em every 60 mins */
  604.     if (curtime > (disc - 24 * 60 * 60) && !quiet) {
  605.         if ((curtime - last) >= (24 * 60 * 60)) {
  606.             autospout = text;
  607.             autospout_free = 0;
  608.             last = curtime;
  609.         }
  610.     }
  611.     return (0);
  612. }
  613.  
  614. newer(char *date, char *path, int showlots)
  615. {
  616.     struct tm tm;
  617.  
  618.     if (sscanf(date, "%04d%02d%02d%02d%02d%02d",
  619.                &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
  620.                &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) {
  621.  
  622.         tm.tm_year -= 1900;
  623.         tm.tm_mon--;
  624.         tm.tm_isdst = -1;
  625.         newer_time = mktime(&tm);
  626.         dout = dataconn("file list", (off_t) - 1, "w");
  627.         /* dout = dataconn("file list", (off_t)-1, "w", 0); */
  628.         transflag++;
  629.         if (dout != NULL) {
  630.  
  631.             show_fullinfo = showlots;
  632. #if defined(HAVE_FTW)
  633.             ftw(path, check_newer, -1);
  634. #else
  635.             treewalk(path, check_newer, -1, NULL);
  636. #endif
  637.  
  638.             if (ferror(dout) != 0)
  639.                 perror_reply(550, "Data connection");
  640.             else
  641.                 reply(226, "Transfer complete.");
  642.  
  643.             (void) fclose(dout);
  644.             data = -1;
  645.         }
  646.     } else
  647.         reply(501, "Bad DATE format");
  648.     transflag = 0;
  649. }
  650.  
  651. int
  652. type_match(char *typelist)
  653. {
  654.     if (anonymous && strcasestr(typelist, "anonymous"))
  655.         return (1);
  656.     if (guest && strcasestr(typelist, "guest"))
  657.         return (1);
  658.     if (!guest && !anonymous && strcasestr(typelist, "real"))
  659.         return (1);
  660.  
  661.     return (0);
  662. }
  663.  
  664. int
  665. path_compare(char *p1, char *p2)
  666. {
  667.     if ( fnmatch(p1, p2, NULL) != 0 )
  668.         return(strlen(p1));
  669.     else
  670.         return(-1);
  671. }
  672.  
  673. void
  674. expand_id(void)
  675. {
  676.     struct aclmember *entry = NULL;
  677.     struct passwd *pwent;
  678.     struct group *grent;
  679.     char buf[BUFSIZ];
  680.  
  681.     while (getaclentry("upload", &entry) && ARG0 && ARG1 && ARG2 != NULL) {
  682.         if (ARG3 && ARG4) {
  683.             pwent = getpwnam(ARG3);
  684.             grent = getgrnam(ARG4);
  685.  
  686.             if (pwent)  sprintf(buf, "%d", pwent->pw_uid);
  687.             else        sprintf(buf, "%d", 0);
  688.             ARG3 = (char *) malloc(strlen(buf) + 1);
  689.             strcpy(ARG3, buf);
  690.  
  691.             if (grent)  sprintf(buf, "%d", grent->gr_gid);
  692.             else        sprintf(buf, "%d", 0);
  693.             ARG4 = (char *) malloc(strlen(buf) + 1);
  694.             strcpy(ARG4, buf);
  695.         }
  696.     }
  697. }
  698.  
  699. int
  700. fn_check(char *name)
  701. {
  702.   /* check to see if this is a valid file name... path-filter <type>
  703.    * <message_file> <allowed_charset> <disallowed> */
  704.  
  705.   struct aclmember *entry = NULL;
  706.   int   j;
  707. #ifdef AMIGA
  708.   regexp *sp;
  709.   int regp;
  710. #else
  711.   char *sp;
  712. #endif
  713.   char *path;
  714.  
  715. #ifdef M_UNIX
  716. # ifdef REGEX
  717.   char *regp;
  718. # endif
  719. #endif
  720.  
  721. #ifdef REGEXEC
  722.   regex_t regexbuf;
  723.   regmatch_t regmatchbuf;
  724. #endif
  725.  
  726.   while (getaclentry("path-filter", &entry) && ARG0 != NULL) {
  727.       if (type_match(ARG0) && ARG1 && ARG2) {
  728.  
  729.           /*
  730.            * check *only* the basename
  731.            */
  732.  
  733.           if (path = strrchr(name, '/'))  ++path;
  734.           else    path = name;
  735.  
  736.           /* is it in the allowed character set? */
  737. #if defined(AMIGA)
  738.           if ((sp = regcomp(ARG2)) == 0) {
  739.               reply(553, "REGEX error");
  740. #elif defined(REGEXEC)
  741.           if (regcomp(®exbuf, ARG2, REG_EXTENDED|REG_ICASE) != 0) {
  742.               reply(553, "REGEX error");
  743. #elif defined(REGEX)
  744.           if ((sp = regcmp(ARG2, (char *) 0)) == NULL) {
  745.               reply(553, "REGEX error");
  746. #else
  747.           if ((sp = re_comp(ARG2)) != 0) {
  748.               perror_reply(553, sp);
  749. #endif
  750.               return(0);
  751.           }
  752. #if defined(AMIGA)
  753.           regp = regexec(sp, path);
  754.           free(sp);
  755.           if (regp == 0) {
  756. #elif defined(REGEXEC)
  757.           if (regexec(®exbuf, path, 1, ®matchbuf, 0) != 0) {
  758. #elif defined(REGEX)
  759. # ifdef M_UNIX
  760.           regp = regex(sp, path);
  761.           free(sp);
  762.           if (regp == NULL) {
  763. # else
  764.           if ((regex(sp, path)) == NULL) {
  765. # endif
  766. #else
  767.           if ((re_exec(path)) != 1) {
  768. #endif
  769.               pr_mesg(553, ARG1);
  770.               reply(553, "%s: Permission denied. (Filename (accept))", name);
  771.               return(0);
  772.           }
  773.           /* is it in any of the disallowed regexps */
  774.  
  775.           for (j = 3; j < MAXARGS; ++j) {
  776.               /* ARGj == entry->arg[j] */
  777.               if (entry->arg[j]) {
  778. #if defined(AMIGA)
  779.                   if ((sp = regcomp(entry->arg[j])) == 0) {
  780.                       perror_reply(553, "REGEX error");
  781. #elif defined(REGEXEC)
  782.                   if (regcomp(®exbuf, entry->arg[j], 
  783.                         REG_EXTENDED|REG_ICASE) !=0) {
  784.                       reply(553, "REGEX error");
  785. #elif defined(REGEX)
  786.                   if ((sp = regcmp(entry->arg[j], (char *) 0)) == NULL) {
  787.                       reply(553, "REGEX error");
  788. #else
  789.                   if ((sp = re_comp(entry->arg[j])) != 0) {
  790.                       perror_reply(553, sp);
  791. #endif
  792.                       return(0);
  793.                   }
  794. #if defined(AMIGA)
  795.                   regp = regexec(sp, path);
  796.                   free(sp);
  797.                   if (regp != 0) {
  798. #elif defined(REGEXEC)
  799.                   if (regexec(®exbuf, path, 1, ®matchbuf, 0) == 0) {
  800. #elif defined(REGEX)
  801. # ifdef M_UNIX
  802.                   regp = regex(sp, path);
  803.                   free(sp);
  804.                   if (regp != NULL) {
  805. # else
  806.                   if ((regex(sp, path)) != NULL) {
  807. # endif
  808. #else
  809.                   if ((re_exec(path)) == 1) {
  810. #endif
  811.                       pr_mesg(553, ARG1);
  812.                       reply(553, "%s: Permission denied. (Filename (deny))", name);
  813.                       return(0);
  814.                   }
  815.               }
  816.           }
  817.       }
  818.   }
  819.   return(1);
  820. }
  821.  
  822. int
  823. dir_check(char *name, uid_t *uid, gid_t *gid, int *valid)
  824. {
  825.   struct aclmember *entry = NULL;
  826.  
  827.   int i,
  828.     match_value = -1;
  829.   char *ap2 = NULL,
  830.        *ap3 = NULL,
  831.        *ap4 = NULL,
  832.        *ap6 = NULL;
  833.   char cwdir[BUFSIZ];
  834.   char path[BUFSIZ];
  835.   char *sp;
  836.   extern struct passwd *pw;
  837.  
  838.   *valid = 0;
  839.  
  840.   strcpy(path, name);
  841. #ifdef AMIGA
  842.   if (sp = strrchr(path, '/'))  *sp = '\0';
  843.   else if (sp = strrchr(path, ':'))  *sp = '\0';
  844.   else path[0] = '\0';
  845. #else
  846.   if (sp = strrchr(path, '/'))  *sp = '\0';
  847.   else strcpy(path, ".");
  848. #endif
  849.  
  850.   if ((realpath(path, cwdir)) == NULL) {
  851.       perror_reply(553, "Could not determine cwdir");
  852.       return(0);
  853.   }
  854.  
  855.   i = match_value;
  856.   while (getaclentry("upload", &entry) && ARG0 && ARG1 && ARG2 != NULL) {
  857.       if ( (!strcmp(ARG0, pw->pw_dir))  &&
  858.            ((i = path_compare(ARG1, cwdir)) >= match_value) ) {
  859.           match_value = i;
  860.           ap2 = ARG2;
  861.           if (ARG3)  ap3 = ARG3;
  862.           else       ap3 = NULL;
  863.           if (ARG4)  ap4 = ARG4;
  864.           else       ap4 = NULL;
  865.           if (ARG6)  ap6 = ARG6;
  866.           else       ap6 = NULL;
  867.       }
  868.   }
  869.  
  870.   if ( ((ap2 && !strcasecmp(ap2, "no")) && (ap3 && strcasecmp(ap3, "dirs"))) || 
  871.         (ap3 && !strcasecmp(ap3, "nodirs")) ||
  872.         (ap6 && !strcasecmp(ap6, "nodirs")) ) {
  873.       reply(530, "%s: Permission denied.  (Upload)", name);
  874.       return(0);
  875.   }
  876.  
  877.   if (ap3)
  878.      *uid = atoi(ap3);    /* the uid  */
  879.   if (ap4) {
  880.      *gid = atoi(ap4);    /* the gid  */
  881.      *valid = 1;
  882.    }
  883.   return(1);
  884. }
  885.  
  886. int
  887. upl_check(char *name, uid_t *uid, gid_t *gid, int *f_mode, int *valid)
  888. {
  889.   int  match_value = -1;
  890.   char cwdir[BUFSIZ];
  891.   char path[BUFSIZ];
  892.   char *sp;
  893.   int  i;
  894.  
  895.   char *ap1 = NULL,
  896.    *ap2 = NULL,
  897.    *ap3 = NULL,
  898.    *ap4 = NULL,
  899.    *ap5 = NULL;
  900.  
  901.   struct aclmember *entry = NULL;
  902.   extern struct passwd *pw;
  903.  
  904.   *valid = 0;
  905.  
  906.       /* what's our current directory? */
  907.  
  908.       strcpy(path, name);
  909. #ifdef AMIGA
  910.       if (sp = strrchr(path, '/'))  *sp = '\0';
  911.       else if (sp = strrchr(path, ':'))  *sp = '\0';
  912.       else path[0] = '\0';
  913. #else
  914.       if (sp = strrchr(path, '/'))  *sp = '\0';
  915.       else strcpy(path, ".");
  916. #endif
  917.  
  918.       if ((realpath(path, cwdir)) == NULL) {
  919.           perror_reply(553, "Could not determine cwdir");
  920.           return(-1);
  921.       }
  922.  
  923.       /* we are doing a "best match"... ..so we keep track of what "match
  924.        * value" we have received so far... */
  925.  
  926.       entry = NULL;
  927.       match_value = -1;
  928.       i = match_value;
  929.       while (getaclentry("upload", &entry) && ARG0 && ARG1 && ARG2 != NULL) {
  930.           if ( (!strcmp(ARG0, pw->pw_dir))  &&
  931.                ((i = path_compare(ARG1, cwdir)) >= match_value) ) {
  932.               match_value = i;
  933.               ap1 = ARG1;
  934.               ap2 = ARG2;
  935.               if (ARG3) ap3 = ARG3;
  936.               else      ap3 = NULL;
  937.               if (ARG4) ap4 = ARG4;
  938.               else      ap4 = NULL;
  939.               if (ARG5) ap5 = ARG5;
  940.               else      ap5 = NULL;
  941.           }
  942.       }
  943.  
  944.       if (ap3 && ( (!strcasecmp("dirs",ap3)) || (!strcasecmp("nodirs", ap3)) ))
  945.         ap3 = NULL;
  946.  
  947.       /* if we did get matches... ..else don't do any of this stuff */
  948.       if (match_value >= 0) {
  949.           if (!strcasecmp(ap2, "yes")) {
  950.               if (ap3)
  951.                   *uid = atoi(ap3);    /* the uid  */
  952.               if (ap4) {
  953.                   *gid = atoi(ap4);    /* the gid  */
  954.           *valid = 1;
  955.         }
  956.               if (ap5)
  957.                   sscanf(ap5, "%o", f_mode); /* the mode */
  958.           } else {
  959.               reply(553, "%s: Permission denied. (Upload)", name);
  960.               return(-1);
  961.           }
  962.       } else {
  963.           /*
  964.            * upload defaults to "permitted"
  965.            */
  966.           return(1);
  967.       }
  968.  
  969.   return(match_value);
  970. }
  971.  
  972. int
  973. del_check(char *name)
  974. {
  975.   int pdelete = 1;
  976.   struct aclmember *entry = NULL;
  977.  
  978.   while (getaclentry("delete", &entry) && ARG0 && ARG1 != NULL) {
  979.       if (type_match(ARG1))
  980.           if (*ARG0 == 'n')
  981.               pdelete = 0;
  982.   }
  983.  
  984.   if (!pdelete) {
  985.       reply(553, "%s: Permission denied. (Delete)", name);
  986.       return(0);
  987.   } else {
  988.       return(1);
  989.   }
  990. }
  991.